<template>
  <div class="home">
    <el-row :gutter="20">
      <!-- 左侧：上传区域 -->
      <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
        <el-card class="upload-card" shadow="hover">
          <div slot="header" class="card-header">
            <span><i class="el-icon-upload"></i> 图片上传</span>
          </div>

          <!-- 拖拽上传区域 -->
          <el-upload
            ref="upload"
            class="upload-area"
            drag
            :action="uploadUrl"
            :before-upload="beforeUpload"
            :on-success="onUploadSuccess"
            :on-error="onUploadError"
            :show-file-list="false"
            :data="uploadData"
            accept="image/*"
            multiple
          >
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">
              将文件拖到此处，或<em>点击上传</em>
            </div>
            <div class="el-upload__tip" slot="tip">
              支持 JPG、PNG、WebP、GIF 格式，单个文件不超过 10MB
            </div>
          </el-upload>

          <!-- 压缩设置 -->
          <div class="compress-settings">
            <h4>压缩设置</h4>
            <el-form :model="compressForm" label-width="80px" size="small">
              <el-form-item label="最大宽度">
                <el-input-number
                  v-model="compressForm.maxWidth"
                  :min="100"
                  :max="4000"
                  controls-position="right"
                />
                <span class="unit">px</span>
              </el-form-item>

              <el-form-item label="最大高度">
                <el-input-number
                  v-model="compressForm.maxHeight"
                  :min="100"
                  :max="4000"
                  controls-position="right"
                />
                <span class="unit">px</span>
              </el-form-item>

              <el-form-item label="压缩质量">
                <el-slider
                  v-model="compressForm.quality"
                  :min="0.1"
                  :max="1.0"
                  :step="0.1"
                  show-input
                  :format-tooltip="formatQuality"
                />
              </el-form-item>

              <el-form-item label="输出格式">
                <el-select
                  v-model="compressForm.outputFormat"
                  placeholder="选择输出格式"
                >
                  <el-option label="JPG" value="jpg"></el-option>
                  <el-option label="PNG" value="png"></el-option>
                  <el-option label="WebP" value="webp"></el-option>
                </el-select>
              </el-form-item>
            </el-form>
          </div>
        </el-card>
      </el-col>

      <!-- 右侧：预览和结果 -->
      <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
        <el-card class="preview-card" shadow="hover">
          <div slot="header" class="card-header">
            <span><i class="el-icon-picture-outline"></i> 图片预览</span>
          </div>

          <!-- 图片预览 -->
          <div v-if="previewImage" class="image-preview">
            <img :src="previewImage" alt="预览图片" class="preview-img" />
            <div class="image-info">
              <p>
                <strong>原始尺寸:</strong> {{ imageInfo.originalWidth }} ×
                {{ imageInfo.originalHeight }}
              </p>
              <p>
                <strong>文件大小:</strong>
                {{ formatFileSize(imageInfo.originalSize) }}
              </p>
            </div>
          </div>

          <!-- 压缩结果 -->
          <div v-if="compressResult" class="compress-result">
            <h4>压缩结果</h4>
            <el-descriptions :column="1" border size="small">
              <el-descriptions-item label="压缩后尺寸">
                {{ compressResult.newWidth }} × {{ compressResult.newHeight }}
              </el-descriptions-item>
              <el-descriptions-item label="压缩后大小">
                {{ formatFileSize(compressResult.compressedSize) }}
              </el-descriptions-item>
              <el-descriptions-item label="压缩比例">
                {{ calculateCompressionRatio() }}%
              </el-descriptions-item>
              <el-descriptions-item label="节省空间">
                {{ formatFileSize(calculateSavedSpace()) }}
              </el-descriptions-item>
            </el-descriptions>

            <div class="action-buttons">
              <el-button type="primary" @click="downloadImage">
                <i class="el-icon-download"></i> 下载压缩图片
              </el-button>
              <el-button @click="resetUpload">
                <i class="el-icon-refresh"></i> 重新上传
              </el-button>
            </div>
          </div>

          <!-- 空状态 -->
          <div v-if="!previewImage && !compressResult" class="empty-state">
            <i class="el-icon-picture-outline"></i>
            <p>请选择图片进行压缩</p>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 上传历史 -->
    <el-card class="history-card" shadow="hover" style="margin-top: 20px">
      <div slot="header" class="card-header">
        <span><i class="el-icon-time"></i> 上传历史</span>
        <el-button size="small" @click="clearHistory">清空历史</el-button>
      </div>

      <el-table :data="uploadHistory" style="width: 100%" size="small">
        <el-table-column prop="fileName" label="文件名" width="200">
          <template slot-scope="scope">
            <span class="file-name">{{ scope.row.fileName }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="originalSize" label="原始大小" width="120">
          <template slot-scope="scope">
            {{ formatFileSize(scope.row.originalSize) }}
          </template>
        </el-table-column>
        <el-table-column prop="compressedSize" label="压缩后大小" width="120">
          <template slot-scope="scope">
            {{ formatFileSize(scope.row.compressedSize) }}
          </template>
        </el-table-column>
        <el-table-column prop="compressionRatio" label="压缩比例" width="100">
          <template slot-scope="scope">
            {{ formatCompressionRatio(scope.row) }}%
          </template>
        </el-table-column>
        <el-table-column prop="timestamp" label="上传时间" width="180">
          <template slot-scope="scope">
            {{ formatTime(scope.row.timestamp) }}
          </template>
        </el-table-column>
      </el-table>
    </el-card>
  </div>
</template>

<script>
import { mapGetters, mapActions } from "vuex";
import Compressor from "compressorjs";

export default {
  name: "Home",
  data() {
    return {
      uploadUrl: "/api/image/compress",
      uploadData: {},
      previewImage: null,
      imageInfo: {},
      compressResult: null,
      compressForm: {
        maxWidth: 1920,
        maxHeight: 1080,
        quality: 0.8,
        outputFormat: "jpg",
      },
      isCompressing: false,
    };
  },
  computed: {
    ...mapGetters(["uploadHistory", "compressConfig"]),
  },
  mounted() {
    this.loadConfig();
  },
  methods: {
    ...mapActions(["addUploadHistory", "setCompressConfig", "clearHistory"]),

    // 加载配置
    async loadConfig() {
      try {
        const response = await this.$http.get("/image/config");
        if (response.data) {
          this.setCompressConfig(response.data);
          this.compressForm.maxWidth = response.data.maxWidth || 1920;
          this.compressForm.maxHeight = response.data.maxHeight || 1080;
        }
      } catch (error) {
        console.error("加载配置失败:", error);
      }
    },

    // 上传前处理
    beforeUpload(file) {
      // 验证文件类型
      const isImage = file.type.startsWith("image/");
      if (!isImage) {
        this.$message.error("只能上传图片文件!");
        return false;
      }

      // 验证文件大小
      const isLt10M = file.size / 1024 / 1024 < 10;
      if (!isLt10M) {
        this.$message.error("图片大小不能超过 10MB!");
        return false;
      }

      // 预览图片
      this.previewImage = URL.createObjectURL(file);
      this.imageInfo = {
        originalWidth: 0,
        originalHeight: 0,
        originalSize: file.size,
      };

      // 获取图片尺寸
      const img = new Image();
      img.onload = () => {
        this.imageInfo.originalWidth = img.width;
        this.imageInfo.originalHeight = img.height;
      };
      img.src = this.previewImage;

      // 前端压缩
      this.compressImage(file);
      return false; // 阻止自动上传
    },

    // 前端压缩
    compressImage(file) {
      this.isCompressing = true;

      new Compressor(file, {
        quality: this.compressForm.quality,
        maxWidth: this.compressForm.maxWidth,
        maxHeight: this.compressForm.maxHeight,
        convertSize: 0, // 不转换大小
        success: (compressedFile) => {
          this.uploadToServer(compressedFile);
        },
        error: (err) => {
          console.error("前端压缩失败:", err);
          this.$message.error("前端压缩失败，将使用原图上传");
          this.uploadToServer(file);
        },
      });
    },

    // 上传到服务器
    async uploadToServer(file) {
      const formData = new FormData();
      formData.append("file", file);

      try {
        const response = await this.$http.post("/image/compress", formData, {
          headers: {
            "Content-Type": "multipart/form-data",
          },
        });

        if (response.data.success) {
          this.onUploadSuccess(response.data);
        } else {
          this.onUploadError(response.data.message);
        }
      } catch (error) {
        this.onUploadError(error.message);
      } finally {
        this.isCompressing = false;
      }
    },

    // 上传成功
    onUploadSuccess(response) {
      this.compressResult = response.data;
      this.$message.success("图片压缩成功!");

      // 添加到历史记录
      this.addUploadHistory({
        ...response.data,
        timestamp: new Date().toISOString(),
      });
    },

    // 上传失败
    onUploadError(error) {
      this.$message.error("上传失败: " + error);
      this.resetUpload();
    },

    // 下载图片
    downloadImage() {
      if (!this.compressResult) return;

      const link = document.createElement("a");
      link.href = `/api/image/download/${this.compressResult.fileName}`;
      link.download = `compressed_${this.compressResult.fileName}`;
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },

    // 重置上传
    resetUpload() {
      this.previewImage = null;
      this.imageInfo = {};
      this.compressResult = null;
      this.$refs.upload.clearFiles();
    },

    // 清空历史
    clearHistory() {
      this.$confirm("确定要清空上传历史吗？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        this.$store.dispatch("clearHistory");
        this.$message.success("历史记录已清空");
      });
    },

    // 格式化文件大小
    formatFileSize(bytes) {
      if (bytes === 0) return "0 B";
      const k = 1024;
      const sizes = ["B", "KB", "MB", "GB"];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
    },

    // 格式化时间
    formatTime(timestamp) {
      return new Date(timestamp).toLocaleString("zh-CN");
    },

    // 格式化质量显示
    formatQuality(value) {
      return (value * 100).toFixed(0) + "%";
    },

    // 计算节省的空间
    calculateSavedSpace() {
      if (!this.compressResult || !this.imageInfo.originalSize) {
        return 0;
      }

      const originalSize = Number(this.imageInfo.originalSize) || 0;
      const compressedSize = Number(this.compressResult.compressedSize) || 0;

      // 确保数据有效
      if (isNaN(originalSize) || isNaN(compressedSize)) {
        return 0;
      }

      const savedSpace = originalSize - compressedSize;
      return Math.max(0, savedSpace); // 确保不会出现负数
    },

    // 计算压缩比例
    calculateCompressionRatio() {
      if (!this.compressResult || !this.imageInfo.originalSize) {
        return 0;
      }

      const originalSize = Number(this.imageInfo.originalSize) || 0;
      const compressedSize = Number(this.compressResult.compressedSize) || 0;

      if (isNaN(originalSize) || isNaN(compressedSize) || originalSize === 0) {
        return 0;
      }

      const ratio = (compressedSize / originalSize) * 100;
      return ratio.toFixed(1);
    },

    // 格式化压缩比例显示
    formatCompressionRatio(row) {
      if (!row.originalSize || !row.compressedSize) {
        return "N/A";
      }
      const originalSize = Number(row.originalSize) || 0;
      const compressedSize = Number(row.compressedSize) || 0;

      if (isNaN(originalSize) || isNaN(compressedSize) || originalSize === 0) {
        return "N/A";
      }

      const ratio = (compressedSize / originalSize) * 100;
      return ratio.toFixed(1);
    },
  },
};
</script>

<style scoped>
.home {
  padding: 20px 0;
}

.upload-card,
.preview-card,
.history-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-header span {
  font-size: 16px;
  font-weight: bold;
}

.card-header i {
  margin-right: 8px;
}

.upload-area {
  width: 100%;
}

.compress-settings {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #ebeef5;
}

.compress-settings h4 {
  margin-bottom: 15px;
  color: #303133;
}

.unit {
  margin-left: 10px;
  color: #909399;
}

.image-preview {
  text-align: center;
  margin-bottom: 20px;
}

.preview-img {
  max-width: 100%;
  max-height: 300px;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.image-info {
  margin-top: 15px;
  text-align: left;
}

.image-info p {
  margin: 5px 0;
  color: #606266;
}

.compress-result {
  margin-top: 20px;
}

.compress-result h4 {
  margin-bottom: 15px;
  color: #303133;
}

.action-buttons {
  margin-top: 20px;
  text-align: center;
}

.action-buttons .el-button {
  margin: 0 10px;
}

.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: #909399;
}

.empty-state i {
  font-size: 48px;
  margin-bottom: 20px;
}

.empty-state p {
  font-size: 16px;
}

.file-name {
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: inline-block;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .home {
    padding: 10px 0;
  }

  .compress-settings .el-form-item {
    margin-bottom: 15px;
  }

  .action-buttons .el-button {
    margin: 5px;
    width: 100%;
  }
}
</style> 